package view;

import java.awt.event.*;
import java.util.LinkedList;

public abstract class Viewport
{
	private final LinkedList<KeyListener> keyListeners;
	private final LinkedList<ActionListener> actionListeners;
	
	public Viewport()
	{
		keyListeners = new LinkedList<KeyListener>();
		actionListeners = new LinkedList<ActionListener>();
	}
	
	public abstract void accept(model.GameCommand gc);
	public abstract void setVisible(boolean visibility);
	public abstract void close();

	/**
	 * Add the specified listener to the Viewport's collection of KeyListeners. All
	 * KeyEvents originating from the Viewport will be forwarded to the listener.
	 * @param listener
	 */
	public void addKeyboardListener(KeyListener listener)
	{
		keyListeners.add(listener);
	}
	
	/**
	 * Removes specified listener from the Viewport's collection of KeyListeners.
	 * @return true if successful
	 */
	public boolean removeKeyboardListener(KeyListener listener)
	{
		return keyListeners.remove(listener);
	}
	
	protected void notifyKeyPressed(KeyEvent ev)
	{
		for (KeyListener listener : keyListeners)
			listener.keyPressed(ev);
	}
	
	protected void notifyKeyReleased(KeyEvent ev)
	{
		for (KeyListener listener: keyListeners)
			listener.keyReleased(ev);
	}

	protected void notifyKeyTyped(KeyEvent ev)
	{
		for (KeyListener listener: keyListeners)
			listener.keyTyped(ev);
	}
	
	/**
	 * Add the specified listener to the Viewport's collection of ActionListeners. All
	 * ActionEvents originating from the Viewport will be forwarded to the listener.
	 * @param listener
	 */
	void addActionListener(ActionListener listener)
	{
		actionListeners.add(listener);
	}

	/**
	 * Removes specified listener from the Viewport's collection of ActionListeners.
	 * @return true if successful
	 */
	public boolean removeActionListener(ActionListener listener)
	{
		return actionListeners.remove(listener);
	}
	
	protected void notifyAction(ActionEvent ev)
	{
		for (ActionListener listener : actionListeners)
			listener.actionPerformed(ev);
	}
	
	/**
	 * This is a utility class that you can add to listen to buttons, frames, or anything
	 * that needs a KeyListener or ActionListener. It will trampoline all the events it
	 * gets the the appropriate listeners registered with the Viewport.
	 */
	protected class TrampolineListener implements KeyListener, ActionListener
	{
		public void keyPressed(KeyEvent ev)
		{
			notifyKeyPressed(ev);
		}

		public void keyReleased(KeyEvent ev)
		{
			notifyKeyReleased(ev);
		}

		public void keyTyped(KeyEvent ev)
		{
			notifyKeyTyped(ev);
		}

		public void actionPerformed(ActionEvent ev)
		{
			notifyAction(ev);
		}
	}
}
